﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Project.EPMAuditing.Library;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.IO;

namespace Microsoft.Office.Project.EPMAuditing.AuditListenerCatalog
{
    public class EventLogAuditListener : AuditListener
    {
        private const string DEFAULT_EVENT_LOG_NAME = "EPMAuditing";
        private const string DEFAULT_EVENT_LOG_SOURCE = "AuditEvent";
        
        private EventLog EPMAuditingEventLog;
        private string _eventLogName;
        private string _eventLogSource;
        private bool _eventLogOpen = false;
        
        #region Construction/Destruction

        public EventLogAuditListener() : this(String.Empty, String.Empty) { }

        public EventLogAuditListener(string eventLogSource) : this(eventLogSource, String.Empty) { }

        public EventLogAuditListener(string eventLogSource, string eventLogName)
        {
            if (!String.IsNullOrEmpty(eventLogSource))
                _eventLogSource = eventLogSource;
            else
                _eventLogSource = DEFAULT_EVENT_LOG_SOURCE;

            if (!String.IsNullOrEmpty(eventLogName))
                _eventLogName = eventLogName;
            else
                _eventLogName = DEFAULT_EVENT_LOG_NAME;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Release managed resources.
                CloseEventLog();
            }
            // Release unmanaged resources.
            // Set large fields to null.

            // Call Dispose on your base class.
            base.Dispose(disposing);
        }
        
        #endregion

        #region Utility Methods

        private void OpenEventLog()
        {
            if (_eventLogOpen)
                CloseEventLog();

            if (!EventLog.Exists(_eventLogName))
            {
                do
                {
                    EventLog.CreateEventSource(_eventLogSource, _eventLogName);
                    Thread.Sleep(1000);
                } while (!EventLog.SourceExists(_eventLogSource));
            }

            if (EPMAuditingEventLog == null)
                EPMAuditingEventLog = new EventLog(_eventLogName, ".", _eventLogSource);

            _eventLogOpen = true;

        }

        private void CloseEventLog()
        {
            if (EPMAuditingEventLog != null)
                EPMAuditingEventLog.Close();
            _eventLogOpen = false;
        }


        #endregion
        
        #region Public Methods

        public override void Write(MemoryStream ms)
        {

            //ChangeRecord changeRecord = DeserializeMessage(ms);
            ChangeRecord changeRecord = new ChangeRecord(ms);
            changeRecord.TracingService = TracingService; 
            if (!_eventLogOpen)
            {
                OpenEventLog();
            }

            // Write the data to the file
            StringBuilder sb = new StringBuilder(8192);
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Event Time      : {0}", changeRecord.EventTime));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Event Name      : {0}", changeRecord.EventName));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Event Source    : {0}", changeRecord.EventSourceName));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Is wWindows User: {0}", changeRecord.EventContextInfo.IsWindowsUser.ToString()));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "User Name       : {0}", changeRecord.EventContextInfo.UserName));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "User GUID       : {0}", changeRecord.EventContextInfo.UserGuid.ToString()));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Tracking GUID   : {0}", changeRecord.EventContextInfo.TrackingGuid.ToString()));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Site GUID       : {0}", changeRecord.EventContextInfo.SiteGuid.ToString()));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "LCID            : {0}", changeRecord.EventContextInfo.Lcid));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "Event Args      : {0}", changeRecord.PSEventArgsXml));
            sb.AppendLine(String.Format(CultureInfo.InvariantCulture, "DataSet Changes : {0}", changeRecord.DataSetChanges));

            EventLog.WriteEntry(_eventLogSource,
                                sb.ToString(),
                                EventLogEntryType.Information,
                                EventLogHelper.EventId(changeRecord.EventSourceName, changeRecord.EventName),
                                EventLogHelper.EventCategory(changeRecord.EventSourceName)
                            );


        }

        #endregion

    }
}
